/**
 * 
 */
package org.zgstudio.ddlchecker;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
 * This class represents a link checking task.
 * 
 * @author zhguo
 * 
 */
public class LinkCheckTask {
    /* description of the link check */
    private String    description;

    /*
     * max number of links to be checked in this task -1 means unlimited This
     * has more precedence than maxMemoryConsumed
     */
    private int       maxLinksToCheck;

    /*
     * max amount of memory to be used by links in this task. unit is byte. -1
     * means unlimited
     */
    private int       maxMemoryConsumed;

    /* urls in this task */
    private List<Link> urlsInTask = new ArrayList<Link>();

    public LinkCheckTask() {
        init("", -1, -1);
    }
    public LinkCheckTask(String desp) {
        init(desp, -1, -1);
    }
    public LinkCheckTask(String desp, int maxLinks, int maxMemory) {
        init(desp, maxLinks, maxMemory);
    }
    
    private void init(String desp, int maxLinks, int maxMemory) {
        this.setDescription(desp);
        this.setMaxLinksToCheck(maxLinks);
        this.setMaxMemoryConsumed(maxMemory);
    }
    
    // ############# URL Addition ##############################

    /*
     * Duplication is not checked.
     */
    public void addURLs(Link links[]) throws TooManyURLsInTaskException {
        Collection<Link> linkColl = Arrays.asList(links);
        addURLs(linkColl);
    }

    public void addURLs(Link links[], boolean checkDup)
            throws TooManyURLsInTaskException {
        Collection<Link> linkColl = Arrays.asList(links);
        addURLs(linkColl, checkDup);
    }

    public void addURLs(Collection<Link> links) throws TooManyURLsInTaskException {
        checkLimits(links.size());
        getUrlsInTask().addAll(links);
    }

    /*
     * Check whether a url exists in this task. Note: Current implementation is
     * not efficient!
     */
    public boolean exists(Link link) {
        for (Iterator<Link> it = getUrlsInTask().iterator(); it.hasNext();) {
            Link linkInTask = it.next();
            if (link.equals(linkInTask))
                return true;
        }
        return false;
    }

    public void addURLs(Collection<Link> links, boolean checkDup)
            throws TooManyURLsInTaskException {
        if (!checkDup)
            addURLs(links);
        else {
            addURLs(links, null);
        }
    }

    /*
     * Add a collection of urls. Those duplicate urls are put in
     * <code>dupColl</code>.
     */
    public void addURLs(Collection<Link> links, Collection<Link> dupColl)
            throws TooManyURLsInTaskException {

        Collection<Link> linksToInsert = new ArrayList<Link>();
        Iterator<Link> it = links.iterator();
        while (it.hasNext()) {
            Link link = it.next();
            if (exists(link)) {
                if (dupColl != null)
                    dupColl.add(link);
            } else
                linksToInsert.add(link);
        }

        addURLs(linksToInsert);
    }

    private void checkLimits(int newUrlAdds) throws TooManyURLsInTaskException {
        int curUrls = getUrlsInTask().size();
        if (maxLinksToCheck != -1) {
            if (newUrlAdds + curUrls > maxLinksToCheck)
                throw new TooManyURLsInTaskException();
        } else if (maxMemoryConsumed != -1) {
            // TODO
        }
    }

    public void clear() {
        getUrlsInTask().clear();
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    public void setMaxLinksToCheck(int maxLinksToCheck) {
        this.maxLinksToCheck = maxLinksToCheck;
    }

    public int getMaxLinksToCheck() {
        return maxLinksToCheck;
    }

    public void setMaxMemoryConsumed(int maxMemoryConsumed) {
        this.maxMemoryConsumed = maxMemoryConsumed;
    }

    public int getMaxMemoryConsumed() {
        return maxMemoryConsumed;
    }

    public void setUrlsInTask(Collection<Link> linksInTask) throws TooManyURLsInTaskException {
        this.clear();
        this.addURLs(linksInTask);
    }

    public Collection<Link> getUrlsInTask() {
        return urlsInTask;
    }
}

class TooManyURLsInTaskException extends Exception {
    private static final long serialVersionUID = 1L;

    public TooManyURLsInTaskException() {
        super();
    }

    public TooManyURLsInTaskException(String message, Throwable cause) {
        super(message, cause);
    }

    public TooManyURLsInTaskException(String message) {
        super(message);
    }

    public TooManyURLsInTaskException(Throwable cause) {
        super(cause);
    }
}
